package com.valuedaas.schoolsafety.service.recources;

import com.alibaba.fastjson.JSON;
import com.mongodb.Block;
import com.mongodb.client.model.Filters;
import com.mongodb.client.model.Projections;
import com.mongodb.client.model.Sorts;
import com.mongodb.client.model.Updates;
import com.valuedaas.schoolsafety.common.collects.sys.SysMenu;
import com.valuedaas.schoolsafety.common.collects.sys.SysRole;
import com.valuedaas.schoolsafety.common.collects.sys.SysUser;
import com.valuedaas.schoolsafety.common.enums.DataStatus;
import com.valuedaas.schoolsafety.controller.resource.vo.MenuVO;
import com.valuedaas.schoolsafety.controller.user.vo.User;
import com.valuedaas.schoolsafety.service.BaseService;
import org.apache.commons.lang3.StringUtils;
import org.bson.Document;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class MenuService extends BaseService {

    @Override
    protected String collName() {
        return SysMenu.COLL_NAME;
    }

    /**
     * 获取所有菜单
     *
     * @return
     */
    public List<Document> getAllMenu() {
        List<Document> menuList = new ArrayList<Document>();
        mongoTemplate.getCollection(collName()).find(Filters.eq(SysMenu.STATUS, DataStatus.NORMAL))
                .sort(Sorts.ascending(SysMenu.ORDER)).into(menuList);
        return menuList;
    }

    /**
     * 获取某用户拥有的所有菜单
     *
     * @param user
     * @return
     */
    @SuppressWarnings("unchecked")
    public List<Document> getUserAuthedMenu(User user) {
        List<Document> menuList = new ArrayList<Document>();
        Set<ObjectId> menuSet = new HashSet<ObjectId>();

        // 查询用户
        final Document userDoc = mongoTemplate.getCollection(collName())
                .find(Filters.eq(SysUser._ID, new ObjectId(user.getUserId())))
                .projection(Projections.include(SysUser.MENUS, SysUser.ROLES)).first();

        // 继承角色菜单
        List<ObjectId> roles = (List<ObjectId>) userDoc.get(SysUser.ROLES);
        if (roles != null) {
            mongoTemplate.getCollection(SysRole.COLL_NAME).find(Filters.in(SysRole._ID, roles))
                    .projection(Projections.include(SysRole.MENUS)).forEach(new Block<Document>() {
                @Override
                public void apply(Document t) {
                    List<ObjectId> menuList = (List<ObjectId>) t.get(SysRole.MENUS);
                    if (menuList != null) {
                        menuSet.addAll(menuList);
                    }
                }
            });
        }
        // 菜单明细列表
        mongoTemplate.getCollection(SysMenu.COLL_NAME).find(new Document(SysMenu._ID, new Document("$in", menuSet))
                .append(SysMenu.STATUS, DataStatus.NORMAL))
                .sort(Sorts.ascending(SysMenu.ORDER)).into(menuList);

        return menuList;
    }

    /**
     * 根据菜单id查询某个菜单详情
     *
     * @param id
     * @return
     */
    public Document get(String id) {
        return mongoTemplate.getCollection(SysMenu.COLL_NAME).find(
                new Document(SysMenu._ID, new ObjectId(id)).append(SysMenu.STATUS, DataStatus.NORMAL))
                .first();
    }

    /**
     * 根据菜单id，逻辑删除某个菜单
     *
     * @param id
     * @return
     */
    public boolean delete(String id) {
        long count = mongoTemplate.getCollection(SysMenu.COLL_NAME).updateOne(Filters.eq(SysMenu._ID, new ObjectId(id)),
                Updates.set(SysMenu.STATUS, DataStatus.DELETE)).getModifiedCount();
        return count > 0;
    }

    public void add(MenuVO menu) {
        Document d = Document.parse(JSON.toJSONString(menu));
        if (StringUtils.isNotEmpty(menu.getParent())) {
            d.put(SysMenu.PARENT, new ObjectId(menu.getParent()));
        }
        mongoTemplate.getCollection(SysMenu.COLL_NAME).insertOne(d);
    }

    public boolean update(MenuVO menu) {
        Document d = Document.parse(JSON.toJSONString(menu));
        d.remove(SysMenu._ID);
        if (StringUtils.isNotEmpty(menu.getParent())) {
            d.put(SysMenu.PARENT, new ObjectId(menu.getParent()));
        }
        return mongoTemplate.getCollection(SysMenu.COLL_NAME)
                .updateOne(Filters.eq(SysMenu._ID, new ObjectId(menu.get_id())), new Document("$set", d)).getMatchedCount() > 0;
    }

    /**
     * 设置用户授权菜单资源
     *
     * @param userId 用户ID
     * @param menus  菜单ID集合
     */
    public void setUserAuthMenu(String userId, Collection<String> menus) {
        List<ObjectId> menuIdList = new ArrayList<>();
        for (String str : menus) {
            menuIdList.add(new ObjectId(str));
        }
        mongoTemplate.getCollection(collName()).updateOne(Filters.eq(SysUser._ID, new ObjectId(userId)),
                Updates.set(SysUser.MENUS, menuIdList));
    }

}